package com.levi.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * topic    rabbitmq配置类
 * 1.创建队列  指定队列的名字，是否持久化
 * 2.创建交换机  指定交换机的类型，名字
 * 3.把队列绑定到交换机并且制定routingkey
 * 4.生产者把消息发送到交换机，交换机根据queue的routingkey把消息发送到不同的队列里面
 * 5.消费者监听队列，消费队列里面的消息
 */
@Configuration
public class RabbitMQConfig {
    public static final String EXCHANGE_NAME = "topic exchange";
    public static final String QUEUT_NAME1 = "queue1";
    public static final String QUEUT_NAME2 = "queue2";

    /**
     * 创建两个队列
     * @return Queue
     *   3个参数: durable:是否持久化,默认是false,持久化队列：会被存储在磁盘上，当消息队列重启时仍然存在，暂存队列：当前连接有效
     *           exclusive:默认也是false，只能被当前创建的连接使用，而且当连接关闭后队列即被删除。此参考优先级高于durable
     *           autoDelete:是否自动删除，当没有生产者或者消费者使用此队列，该队列会自动删除。
     *     一般设置一下队列的持久化就好,其余两个就是默认false
     */
    @Bean
    public Queue queue1() {
        return new Queue(QUEUT_NAME1,true);
    }

    @Bean
    public Queue queue2() {
        return new Queue(QUEUT_NAME2,true);
    }

    /**
     * 创建 Topic类型的交换机
     * @return
     */
    @Bean
    TopicExchange exchange() {
        return new TopicExchange(EXCHANGE_NAME);
    }

    /**
     * 队列绑定到交换机
     * @param queue1
     * @param exchange
     * @return
     */
    @Bean
    Binding bindingExcchangeMessage1(Queue queue1, TopicExchange exchange) {
        return BindingBuilder.bind(queue1)
                .to(exchange)
                .with("dog.red");
    }

    @Bean
    Binding bindingExcchangeMessage2(Queue queue2, TopicExchange exchange) {
        return BindingBuilder.bind(queue2)
                .to(exchange)
                .with("dog.#");
    }



    /**
     * 设置带有ttl的 Queue
     * 一般用于一些特殊的场景:下单之后再一定的时间内没有支付成功，就把该消息删除掉，或者放入死信队列中
     * 设置ttl有两种方式
     * 1.给队列设置ttl，往队列里面发送消息 （比较常用）
     * 2.给消息设置ttl
     * 注意:如果把队列和消息都设置了过期时间，以最短时间为准
     * @return
     */
    @Bean
    public Queue queueTtl() {
        Map<String, Object> args = new HashMap<>();
        //设置过期时间
//        args.put("x-message-ttl", 5000);
        //绑定死信队列，过期的消息会放到私信队列里面去,fanout模式不用设置 routingkey
        args.put("x-dead-letter-exchange", "deadTopicExchange");
        args.put("x-dead-letter-routing-key", "dead");
        return new Queue("ttl", true, false, false,args);
    }

    @Bean
    Binding bindingExcchangeTtl(Queue queueTtl, TopicExchange exchange) {
        return BindingBuilder.bind(queueTtl)
                .to(exchange)
                .with("ttl");
    }

    /**
     * 创建一个普通队列
     * @return
     */
    @Bean
    public Queue ttlMsgQueue() {
        return new Queue("ttlmsg",true);
    }

    /**
     * 绑定新的队列和交换机，用于测试  ttlmsg
     * @param ttlMsgQueue
     * @param exchange
     * @return
     */
    @Bean
    Binding bindingExcchangeTtlMessage(Queue ttlMsgQueue, TopicExchange exchange) {
        return BindingBuilder.bind(ttlMsgQueue)
                .to(exchange)
                .with("ttlmsg");
    }

}
